// ==UserScript==
// @name         微博文章转Word专业版
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  使用html-docx-js生成更专业的Word文档
// @author       YourName
// @match        *://weibo.com/1576730592/*
// @match        *://weibo.com/ttarticle/*
// @match        *://*.weibo.com/article/*
// @grant        GM_xmlhttpRequest
// @grant        GM_openInTab
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM_deleteValue
// @grant        GM_listValues
// @require      https://unpkg.com/html-docx-js@0.3.1/dist/html-docx.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
// @run-at       document-end
// ==/UserScript==

(function() {
    'use strict';

    class CacheManager {
        // 默认缓存时间1小时(单位：毫秒)
        static DEFAULT_EXPIRE = 60 * 60 * 1000;

        // 设置缓存
        static setItem(key, value, expire = this.DEFAULT_EXPIRE) {
            const data = {
                value: JSON.stringify(value),
                expire: Date.now() + expire
            };
            GM_setValue(key, JSON.stringify(data));
        }

        // 获取缓存
        static getItem(key) {
            const rawData = GM_getValue(key, null);
            if (!rawData) return null;

            try {
                const data = JSON.parse(rawData);
                if (Date.now() > data.expire) {
                    this.delete(key);
                    return null;
                }
                return JSON.parse(data.value);
            } catch (e) {
                this.delete(key);
                return null;
            }
        }

        // 删除缓存
        static deleteItem(key) {
            GM_deleteValue(key);
        }

        // 清空所有缓存
        static clear() {
            GM_listValues().forEach(key => this.deleteItem(key));
        }

        // 获取缓存状态
        static info() {
            return GM_listValues().map(key => {
                const data = JSON.parse(GM_getValue(key));
                return {
                    key,
                    expire: new Date(data.expire),
                    size: data.value.length
                };
            });
        }
    }


    function isBaseUrl(url){
        const pattern = /^https:\/\/weibo\.com\/1576730592(?:\/[^?#]*)?(?:\?[^#]*)?$/;
        return pattern.test(url);
    }

    function isArticleUrl(url){
        return url.toString().indexOf('article')>-1;
    }

    // 如果重新执行脚本，把缓存清空
    if (isBaseUrl(window.location.href)) {
        CacheManager.clear();
        console.log("清除缓存成功");
    }

    const sleep = (timeout) => {
        return new Promise((resolve) => {
            setTimeout(() => {
                resolve();
            }, timeout);
        });
    }; //睡眠函数用于等待。

    // 提取有效链接
    const links = ()=>{
        // 获取目标容器
        const container = document.querySelector('div.detail_wbtext_4CRf9');
        let hrefArray=Array.from(container.querySelectorAll('a'))
        .map(a => ({
            text: a.textContent.trim(),
            href: a.href
        }))
        .filter(link =>
                !link.text.includes('常态化面试学习每日提醒')&&
                link.href &&
                !link.href.startsWith('javascript:') &&
                link.text.length > 0
                &&isArticleUrl(link.href)
               );

        if (hrefArray.length === 0) {
            console.error('未找到有效链接');
            return;
        }

        return hrefArray;
    }

    // 专业内容提取器
    const extractContent = () => {
        let isFirstParagraph = true;  // 首段标记
        let articleNode = document.querySelector('.art-con-new');
        if (!articleNode) {
            articleNode=document.querySelector('.WB_editor_iframe_new');
        }
        if (!articleNode) {
            articleNode=document.querySelector('.WB_editor_iframe');
        }
        if (!articleNode) {
            return '\n';
        }
        // 高级清理策略
        const forbiddenSelectors = [
            'script', 'style', 'iframe',
            '.ad-box', '.recommend-box',
            '[style*="display:none"]'
        ];

        forbiddenSelectors.forEach(selector => {
            articleNode.querySelectorAll(selector).forEach(el => el.remove());
        });

        // 结构化转换
        let html= Array.from(articleNode.children).map(el => {
            const tag = el.tagName.toLowerCase();
            let pContent = el.innerHTML.trim();
            //console.log('tag:'+tag+'content:'+pContent);
            // 首段加粗处理
            if (isFirstParagraph) {
                pContent = `<strong>`+pContent+`</strong>`;
                isFirstParagraph = false;
            }
            if (pContent.includes('以下内容仅V+会员可见')||pContent==='<br>'||pContent==='&nbsp;') {
                return '';
            }
            else{
                return `<p style="font-size:14pt; line-height:1; text-indent:2em; margin:0;">${pContent}</p>`;
            }
        }).join('');
        return html;
    };

    // 生成Word文档（使用html-docx-js）
    const generateWordDocument = (content) => {
        // 专业Word模板
        const fullHtml = `
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="UTF-8">
                <style>
                    body {
                        font-family: ${FONT_CONFIG.primary}, ${FONT_CONFIG.fallback}, ${FONT_CONFIG.backup};
                        margin: 2cm 3cm;
                    }
                    .quote {
                        border-left: 4px solid #FF8200;
                        padding-left: 12px;
                        margin: 15px 0;
                    }
                    .word-section{
                        margin:0;
                        white-space:pre-line;
                    }
                </style>
            </head>
            <body>
                ${content}
            </body>
            </html>
        `;

        // 转换为Word兼容格式
        return htmlDocx.asBlob(fullHtml, {
            orientation: 'portrait',
            margins: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1英寸边距（1440 twip = 1 inch）
        });
    };

    // 字体配置常量
    const FONT_CONFIG = {
        primary: 'SimSun',     // 主字体：宋体
        fallback: '宋体',      // 备用名称
        backup: 'Microsoft YaHei'  // 备用字体
    };

    const main = ()=>{
        console.log('window.location.href:',window.location.href);
        const articleUrlListKey='articleUrlListKey';
        const articleUrlListLenthKey='articleUrlListLenthKey';
        const currentArticleIndexKey='currentArticleIndexKey';
        const articleContentKey='articleContentKey';
        const outputWordDocKey='outputWordDocKey';
        const isOpenArticleKey='isOpenArticleKey';

        // 如果是文章页面，拼接字符串
        if(isArticleUrl(window.location.href)){
            console.log('文章页面')
            let currentArticleIndex=parseInt(CacheManager.getItem(currentArticleIndexKey));
            const articleUrlList=JSON.parse(CacheManager.getItem(articleUrlListKey));
            console.log('把第'+currentArticleIndex+'个链接'+articleUrlList[currentArticleIndex].href+'转为文本');
            let content=extractContent();
            console.log('转化后的文本信息为',content);
            let articleContent=JSON.parse(CacheManager.getItem(articleContentKey));
            articleContent.push(content);
            CacheManager.setItem(articleContentKey,JSON.stringify(articleContent));
            // 如果已经拼接完成，则输出word文档
            if (currentArticleIndex==articleUrlList.length-1) {
                if (!CacheManager.getItem(outputWordDocKey)) {
                    console.log('已完成全部文本的拼接，输出word文档');
                    let results=JSON.parse(CacheManager.getItem(articleContentKey));
                    CacheManager.setItem(outputWordDocKey,true);
                    const finalContent = results.join('<br/><br/>');
                    //console.log('最后拼接的文本内容为：',finalContent);
                    // 生成文档
                    const blob = generateWordDocument(finalContent);
                    // 保存文件
                    saveAs(blob, `微博文章_${Date.now()}.docx`);
                }else{
                    console.log('已完成word文档的输出，忽略......');
                }
                return;
            }
            CacheManager.setItem(currentArticleIndexKey,currentArticleIndex+1);
            console.log('重定向到',articleUrlList[currentArticleIndex].href);
            window.location=articleUrlList[currentArticleIndex+1].href;
            // 拼接完成，关闭页面
            // window.close();
        }
        // 如果是列表页面，跳到下一個文章页面
        else if (isBaseUrl(window.location.href)) {
            if (!CacheManager.getItem(currentArticleIndexKey)) {
                // 获取a标签信息
                let hrefArray=links();
                console.log('获取a标签信息完成',hrefArray);
                CacheManager.setItem(articleUrlListKey,JSON.stringify(hrefArray));
                CacheManager.setItem(articleUrlListLenthKey,hrefArray.length);
                CacheManager.setItem(currentArticleIndexKey,0);
                CacheManager.setItem(articleContentKey,JSON.stringify([]));
            }
            const articleUrlList=JSON.parse(CacheManager.getItem(articleUrlListKey));
            let currentArticleIndex=parseInt(CacheManager.getItem(currentArticleIndexKey));
            //window.open(articleUrlList[currentArticleIndex].href,'_blank');
            if (!CacheManager.getItem(isOpenArticleKey)) {
                CacheManager.setItem(isOpenArticleKey,true);
                GM_openInTab(articleUrlList[currentArticleIndex].href, {
                    active: true,          // 是否聚焦新标签页
                    insert: true,          // 插入到当前标签右侧
                    setParent: false       // 关闭父标签时不关闭此标签
                });
                //window.location=articleUrlList[currentArticleIndex].href;
            }else{
                console.log('已经打开文章页面，忽略')
                return;
            }
            //window.location.reload();
        }
    }

    setInterval(function () {
        main();
    }, 3000);

})();